/******************************************************************************
 * The Unofficial IRC API for C                                               *
 * Started 12-5-2005                                                          *
 * Not Completed (PRE-ALPHA WORK IN PROGRESS)                                 *
 * Executive Author: Dustin Molieri dmolieri@users.sourceforge.net            *
 * E-Mail the author if you would like to contribute your expertise.          *
 *                                                                            *
 * DESCRIPTION                                                                *
 *                                                                            *
 * Unofficial C API for RFC1459 client to server communication using IRC      *
 * protocol. Designed for developers who would like to integrate IRC          *
 * communication into their application without knowledge of the IRC          *
 * protocol. This API was designed to be as easy to use as the MySQL API      *
 * would be for connecting to a SQL server. This API gives developers the     *
 * ability to build a complete IRC client with little to no understanding of  *
 * the IRC protocol.                                                          *
 *                                                                            *
 * This project is licensed using the GNU Public License Agreement (GPL)      *
 ******************************************************************************/
 
#define CIRCAPI_H
#define NO_TEXT	-1
#define HUGEBUFF 262144
#define BIGBUFF 65536
#define SMALLBUFF 8192
#define TINYBUFF 32
#define NICKLEN 32
#define USERLEN 32
#define CHANLEN 32
#define TOPICLEN 128


/************************
 * Structures & Classes *
 ************************/
 
 // Uses dynamic string allocation
 // IRC ORGANIZED FORMATTED STRUCTURE
struct ircofs	
{
	// Basic Stringlist Section
	int line_ct;
	char **ln;
};

struct ircuser
{
	char nick[NICKLEN];			// user nick
	int active;					// user field active?
	unsigned char op;			// op?
	unsigned char voice;		// voice?
};

struct ircchannel
{
	char name[CHANLEN];
	unsigned char active;
	
	int user_field_ct;
	int user_active_ct;
	struct ircuser *users;
};

struct t_channels
{
	int field_ct;
	int active_ct;
	struct ircchannel *channels;
};

#define PING_MSG	 		10
#define CHANNEL_PRIVMSG_MSG		20
#define USER_PRIVMSG_MSG		30
#define MODE_CHANGE_MSG			40
#define DISCONNECT_MSG			50
#define USER_JOIN_MSG			60
#define USER_PART_MSG			70
#define USER_QUIT_MSG			80
#define CHANNEL_NAMES_MSG		90
#define CHANNEL_NAMES_COMPLETE_MSG	100
#define CHANNEL_JOIN_REJECT_MSG		110
#define USER_NICK_CHANGE_MSG		120
#define MOTD_MSG			130
#define MOTD_END_MSG			140
#define NOTICE_MSG			150
#define WELCOME_MSG			160
#define YOURHOST_MSG			170
#define CREATED_MSG			180
#define MYINFO_MSG			190
#define BOUNCE_MSG			200
#define NOTICEAUTH_MSG			210
#define UNKNOWN_MSG			400


/******************
 * Root Functions *
 ******************/
 
// connect to the irc server
int irc_connect(int *sockfd, char *srv, char *port, char *nick, char *user, unsigned char invisible, char *name, int options, ...);

// disconnect from the irc server
int irc_disconnect(int *sockfd);

// send text to server exactly as it is
int irc_send_server_text(int *sockfd, char *text);

// get raw text from server exactly as it is (raw)
int irc_get_server_text(int *sockfd, char *buff, int buff_len);

// send a private message (undisciplined)
int irc_privmsg(int *sockfd, char *dest, char *message);
												
/*********************************
 * Disciplined Message Functions *
 *********************************/

int irc_send_channel_text(int *sockfd, char *channel, char *text);	// sends text to a channel
int irc_send_user_text(int *sockfd, char *nick, char *text); // sends text to a user

/******************************************************
 * These functions use root functions for interaction *
 ******************************************************/												
 
int irc_join_channel(int *sockfd, char *channel);				// join a channel on the irc server, returns 1 on success, 0 on failure (/join)
int irc_leave_channel(int *sockfd, char *channel);				// leave a channel on the irc server, returns 1 on success, returns 0 on failure (/leave)
int irc_change_nick(int *sockfd, char *nick);					// change nickname on the irc server, returns 1 on success, 0 on failure (/nick)
int irc_message_user(int *sockfd, char *nick, char *msg);		// Message a user on the IRC server, returns 1 on success, 0 on failure (/msg)
int irc_message_channel(int *sockfd, char *channel, char *msg);	// Message a channel (/me)
int irc_set_topic(int *sockfd, char *channel, char *topic);		// Change the topic of a channel
int irc_give_voice(int *sockfd, char *nick, char *channel);		// Gives user voice (must be channel op)
int irc_give_op(int *sockfd, char *nick, char *channel);		// Gives user op status (must be channel op)
int irc_nick_list(int *sockfd, char *channel);					// Summons a nick list

/************************
 * IRC Channel Handling *
 ************************/

int irc_channels_cleanup(struct t_channels *ircch);						// sorts channel names alphabetically
int irc_t_channels_init(struct t_channels *ircch);					// initializes t_channels structure
int irc_ircchannel_init(struct ircchannel *ch);						// initializes ircchannel structure
int irc_clear_ircchannel(struct ircchannel *channel);				// clears ircchannel structure
int irc_clear_t_channels(struct t_channels *ircch);					// clear t_ircchannel structure
int irc_create_first_channel(struct t_channels *ircch, char *name);	// create the first channel in the channel list
int irc_append_channel(struct t_channels *ircch, char *name); 		// append a new channel or use an unused one
int irc_recycle_channel(struct t_channels *ircch, char *name);		// use an unused channel
int irc_channel_deactivate(struct t_channels *ircch, char *name);// deactivate a channel (usually on part or join reject)

/*********************
 * IRC User Handling *
 *********************/
 
int irc_create_first_user(struct ircchannel *ch, char *nick);		// create first user field in a channel using nick
int irc_append_user(struct ircchannel *ch, char *nick);				// append a user field to a channel using nick
int irc_recycle_user(struct ircchannel *ch, char *nick);			// recycle an inactivue user field using nick
int irc_user_deactivate(struct ircchannel *ch, char *nick);			// deactivate user <nick> from channel <ch>
int irc_adduser(char *joinmsg, struct t_channels *ircch);			// adds a user to channel
int irc_adduser2(char *nick, char *channel, struct t_channels *ircch); // same as adduser but uses nick/channel instead of join message
int irc_remuser(char *partmsg, struct t_channels *ircch);			// deactivates based on a part message
int irc_remuser2(char *nick, char *channel, struct t_channels *ircch);	// same as remuser but uses nick/channel instead
int irc_remuser3(char *quitmsg, struct t_channels *ircch);			// deactivates based on a quit message (from every channel)
int irc_addusers(char *nickmsg, struct t_channels *ircch);			// adds to irc channel using a user list
int irc_addircuser(struct ircchannel *dest, struct ircuser src);	// adds given ircuser structure to channel structure
int irc_remircuser(char *nick_name, char *channel_name, struct t_channels *ircch); // removes given ircuser by evaluating nick & channel instead of partmsg
int irc_ircuser_init(struct ircuser *ircusr);						// initializes ircuser structure
int irc_clear_ircuser(struct ircuser *user);						// clears ircuser structure
int irc_user_nickchange(char *nickchangemsg, struct t_channels *ircch); // changes the nick of a user in all channels

/**************************************************************************
 * This group of functions can tell you what a line of text is (or isn't) *
 **************************************************************************/
 
unsigned char irc_is_ping(char *ln);				// is it a ping?
unsigned char irc_is_channel_message(char *ln);		// is it a message to a channel?
unsigned char irc_is_user_message(char *ln);		// is it a private message from a user?
unsigned char irc_is_mode_message(char *ln);		// is it a mode change message?
unsigned char irc_is_disconnect_message(char *ln);	// is it a disconnect message?
unsigned char irc_is_join_message(char *ln);		// is it a user joined message?
unsigned char irc_is_part_message(char *ln);		// is it a user departed channel message?
unsigned char irc_is_quit_message(char *ln);		// is it a user disconnected from the irc network message?
unsigned char irc_is_nick_list(char *ln);           	// is it a numeric 353 channel list message?
unsigned char irc_is_nick_list_complete(char *ln);	// is it a numeric 366 end of /NAMES list
unsigned char irc_is_join_reject(char *ln);		// is it a channel join rejection message?
unsigned char irc_is_nick_change(char *ln);		// did someone change their nick?
unsigned char irc_is_welcome_message(char *ln);		// is it a welcome message 001?
unsigned char irc_is_yourhost_message(char *ln);	// is it a yourhost message 002?
unsigned char irc_is_created_message(char *ln);		// is it a created message 003?
unsigned char irc_is_myinfo_message(char *ln);		// is it a myinfo message 004?
unsigned char irc_is_bounce_message(char *ln);		// is it a bounce message 005?
unsigned char irc_is_notice_auth_message(char *ln);	// is it a NOTICE AUTH message? (non-numeric)

unsigned int irc_translate(char *ln);			// return a translated message type

/************************************************************************************
 * Extract info related to the text recieved & store it into a \0 terminated buffer *
 ************************************************************************************/
 
char *irc_numeric(char *ln, char *dest);			// stores & returns numeric
char *irc_sender(char *ln, char *dest);				// stores & returns nick!ip@server info
char *irc_sender_nick(char *ln, char *dest);		// stores & returns just the nick of the user
char *irc_sender_ip(char *ln, char *dest);			// stores & returns the sender's ip address
char *irc_sender_channel(char *ln, char *dest);		// stores & returns the sender's channel
char *irc_numeric_channel(char *ln, char *dest);	// stores & returns the channel referring the numeric message
char *irc_sender_message(char *ln, char *dest);		// stores & returns the sender's message

/*****************************************************
 * These functions are for dealing with server input *
 *****************************************************/
 
int irc_ircofs_init(struct ircofs *ofs);				// Initializes ircofs structure
int irc_buff2ircofs(struct ircofs *ofs, char *buff);	// Converts a buffer into an ircofs structure
int irc_clear_ircofs(struct ircofs *ofs);				// frees memory used for dynamic string allocation

/******************************************************
 * Other Functions                                    *
 ******************************************************/

void nonblocking(int *sockfd);
void irc_precall();									// called internally by irc api functions to prepare 
char *irc_error();									// get error message (if any)
char *irc_ping_responce(char *ln, char *dest);		// takes a ping line and formats a ping responce
char *channel_index_text(char *str);				// returns a pointer to the first #<channel> or &<channel> in char *str
int compare(char *str1, char *str2);				// case insensitive strcmp
int comparen(char *str1, char *str2, int len);		// case insensitive strncmp
char *index2string(char *dest, char *src);		// takes the first word (all letters prior to first space) and transforms to \0 string

/***********************************
 * Functions to index your pointer *
 ***********************************/

char *ping_message_index_ping(char *pingmsg);		// returns pointer to the ping id in the ping message, NULL if not pingmsg
char *channel_message_index_channel(char *chanmsg); // returns pointer to the channel in the channel message, NULL if not chanmsg
char *user_message_index_nick(char *usermsg);		// returns pointer to the user in the user message, NULL if not usermsg
char *mode_message_index_mode(char *modemsg);		// return pointer to the mode change in mode message, NULL if not modemsg
char *disconnect_message_index_reason(char *discmsg); // return pointer to the disconnect message reason, NULL if not discmsg
char *join_message_index_nick(char *joinmsg);		// return pointer to the nick of the joining user, NULL if not joinmsg
char *join_message_index_channel(char *joinmsg); 	// return pointer to the channel of the joining user, NULL if not joinmsg
char *part_message_index_nick(char *partmsg);		// return pointer to the nick of the parting user, NULL if not partmsg
char *quit_message_index_nick(char *quitmsg);		// return pointer to the nick of the person that quit, NULL if not quitmsg
char *quit_message_index_reason(char *quitmsg); 	// return pointer to the reason the person quit, NULL if not quitmsg
char *nick_list_index_first_nick(char *nicklistmsg); // return pointer to first nick in the nick list, NULL if not nicklistmsg
char *nick_list_index_channel(char *nicklistmsg);	// return a pointer to the channel in the nick list, NULL if not nicklistmsg
char *join_reject_index_channel(char *joinrejectmsg); // return pointer to channel name of channel reject, NULL if not joinrejectmsg
char *nick_change_index_oldnick(char *nickchangemsg); // return a pointer to the person's old nick
char *nick_change_index_newnick(char *nickchangemsg); // return a pointer to the person's new nick
char *motd_index_message(char *motdmsg);			// return a pointer to the motd message, NULL if not noticemsg
char *motd_end_index_message(char *motdmsg);			// return a pointer to the end motd message, NULL if not noticemsg
char *notice_index_message(char *noticemsg);			// return a pointer to the notice message, NULL if not noticemsg

char *welcome_message_index_message(char *welcomemsg);		// return a pointer to 001 welcome message, NULL if not 001
char *yourhost_message_index_message(char *yourhostmsg);	// reutrn a pointer to 002 yourhost message, NULL if not 002
char *created_message_index_message(char *createdmsg);		// return a pointer to 003 server created message, NULL if not 003
char *myinfo_message_index_message(char *myinfomsg);		// return a pointer to 004 my info message, NULL if not 004
char *bounce_message_index_message(char *bouncemsg);		// return a pointer to 005 bounce message, NULL if not 005

char *notice_auth_message_index_message(char *noticemsg);	// return a pointer to NOTICE AUTH message

char *rpl_index_message(char *numeric, char *message);	// return a pointer to standard rpl numeric message :some.host #NUMERIC#--->: <message>



